#ifndef GAMEENGINE_GEOMETRY_PARALLELOGRAM2D_H
#define GAMEENGINE_GEOMETRY_PARALLELOGRAM2D_H

#include <GameEngine/Geometry/geometry_settings.h>

#include <GameEngine/Geometry/Location/point2d.h>
#include <GameEngine/Geometry/Location/vector2d.h>
#include <GameEngine/Geometry/Lines/line2d.h>
#include <GameEngine/Geometry/Core/coords2d.h>
#include <GameEngine/Geometry/CoordinateSystems/transformer2d.h>


#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif

namespace Parallelogram2D {
	//! Point index along a parallelogram
	enum Index {
		//! First point
		/*!
		 @note This is point at parametric coordinates (0,0), i.e., the
		       origin of the parallelogram
		 */
		First = 0,
		//! Second point
		/*!
		 @note This is point at parametric coordinates (1,0)
		 */
		Second = 1,
		//! Third point
		/*!
		 @note This is point at parametric coordinates (0,1)
		 */
		Third = 2,
		//! Fourth point
		/*!
		 @note This is point at parametric coordinates (1,1)
		 */
		Fourth = 3
	};
}



//! Class used to represent 2D parallelograms
/*!
 @note A 2D parallelogram is made of an origin and two non-colinear vectors
 @note Most algorithms expect floating point operations. Type T should therefore
       not be an integer type
 @todo Setup unit tests
 */
template <class T>
class Parallelogram2d {

public:
	Parallelogram2d();
	Parallelogram2d(const Point2d<T>& origin, const Vector2d<T>& v1, const Vector2d<T>& v2);
	Parallelogram2d(const Parallelogram2d& rhs);
	virtual ~Parallelogram2d();
	Parallelogram2d& operator=(const Parallelogram2d& rhs);

	Point2d<T>& origin();
	const Point2d<T>& origin() const;
	Vector2d<T>& v1();
	const Vector2d<T>& v1() const;
	Vector2d<T>& v2();
	const Vector2d<T>& v2() const;

	Point2d<T> point(const Coords2d<T>& coords) const;
	Coords2d<T> coordinates(const Point2d<T>& pt) const;
	Transformer2d<T> transformer() const;
	Point2d<T> operator[](Parallelogram2D::Index index) const;

	bool inside(const Point2d<T>& rhs, bool strict = false) const;
	int intersection(const Line2d<T>& rhs, T& line_coordinate1, T& line_coordinate2, IntersectionType::Type* type = nil) const;
	bool closest_point(const Point2d<T>& rhs, Coords2d<T>& coords) const;
	Point2d<T> closest_point(const Point2d<T>& rhs) const;

	T perimeter() const;
	T area() const;

	bool degenerate(const T& tolerance = 0.000001) const;
	static bool in_parallelogram(const Coords2d<T>& coords, bool strict=false);

protected:
	//! Origin of the parallelogram
	Point2d<T> origin_;

	//! First vector
	Vector2d<T> v1_;

	//! Second vector
	Vector2d<T> v2_;
};

#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif

#include <GameEngine/Geometry/Surfaces/parallelogram2d.hpp>

#endif
